home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-11 | 4.2 KB | 87 lines | [TEXT/????] |
- (define-macro (define-crecord record-name fields)
- (let* ((record-name-string (symbol->string record-name))
- (constructor-name (intern (string-append "MAKE-" record-name-string)))
- (indexer-name (intern (string-append record-name-string "-ADDRESS")))
- (size-name (intern (string-append record-name-string "-SIZE")))
- (field-macros '())
- (field-offset 0)
- (make-field-macros
- (named-lambda make-field-macros (field-def)
- (let* ((field-name (first field-def))
- (field-name-string (symbol->string field-name))
- (field-type-name (second field-def))
- (field-type (crecord-type field-type-name))
- (field-is-array? (not (null? (cddr field-def))))
- (field-count (if field-is-array? (third field-def) 1))
- (field-size (get-crecord-type-size field-type))
- (getter-name (intern (string-append record-name-string "-" field-name-string)))
- (get-addr-name (intern (string-append record-name-string "-" field-name-string "-ADDRESS")))
- (setter-name (intern (string-append "SET-" record-name-string "-" field-name-string "!")))
- (offset-name (intern (string-append record-name-string "-" field-name-string "-OFFSET"))))
- (push! `(define-macro (,getter-name record &optional i)
- (if i
- `(get-crecord-field ,record ,(simplify-index ,field-offset ,field-size i) ,,field-type)
- `(get-crecord-field ,record ,,field-offset ,,field-type))) field-macros)
- (push! `(define-macro (,get-addr-name record &optional i)
- (if i
- `(get-crecord-field-address ,record ,(simplify-index ,field-offset ,field-size i) 'pointer)
- `(get-crecord-field-address ,record ,,field-offset 'pointer))) field-macros)
- (push! `(define-macro (,setter-name record value &optional i)
- (if i
- (let ((value i) ; looks better to have index before value
- (i value))
- `(set-crecord-field! ,record ,(simplify-index ,field-offset ,field-size i) ,,field-type ,value))
- `(set-crecord-field! ,record ,,field-offset ,,field-type ,value))) field-macros)
- (push! `(define ,offset-name ,field-offset) field-macros)
- (+ field-offset (* field-size field-count))))))
- (let loop ((fields fields))
- (when fields
- (let ((field-def (car fields)))
- (if (atom? (car field-def))
- (set! field-offset (make-field-macros field-def))
- (let ((new-offset field-offset))
- (let field-loop ((fields field-def))
- (when fields
- (let* ((field-def (car fields))
- (this-offset (make-field-macros field-def)))
- (when (> this-offset new-offset)
- (set! new-offset this-offset))
- (field-loop (cdr fields)))))
- (set! field-offset new-offset)))
- (loop (cdr fields)))))
- (push! `',record-name field-macros)
- `(begin
- (define-macro (,constructor-name &optional size)
- (if size
- `(allocate-cmemory ',',record-name (* ,,field-offset ,size))
- `(allocate-cmemory ',',record-name ,,field-offset)))
- (define-macro (,indexer-name record i)
- `(get-crecord-field-address ,record (* ,,field-offset ,i) 'pointer))
- (define ,size-name ,field-offset)
- ,@(reverse field-macros))))
-
- (define (simplify-index base size i)
- (let ((offset (if (number? i)
- (* size i)
- (if (= size 1)
- i
- `(* ,size ,i)))))
- (if (= base 0)
- offset
- (if (number? offset)
- (+ base offset)
- `(+ ,base ,offset)))))
-
- (define (crecord-type name)
- (case name
- (char 1)
- (uchar 2)
- (short 3)
- (ushort 4)
- (int 5)
- (uint 6)
- (long 7)
- (ulong 8)
- (ptr 9)
- (else (error "unknown type ~S" name))))
-